#ifndef INFINITY_SERVICE_MANAGER_H
#	define INFINITY_SERVICE_MANAGER_H

#include "service.h"
#include "servicekey.h"

namespace infinity {

class ServiceManager
{
public : //! @name Construction & Destruction
	//! @{
	ServiceManager();
	virtual ~ServiceManager();
	//! @}

public : //! @name Commands
	//! @{
	void registerDependency(const ServiceKey& service, const ServiceKey& dependency);

	template< class T >
	void createService();

	void update(dw::float32 deltaT);

	void destroyAllServices();

	virtual void renderDebug();
	//! @}

public : //! @name State
	//! @{
	Service& getService(const ServiceKey& key);

	template< class T >
	T& getService();
	//! @}

private : //! @name Types definitions
	//! @{
	typedef std::vector< ServiceKey > DependenciesCollection;

	struct ServiceHolder
	{
		ServiceHolder() : service(NULL) { ; }
		ServiceKey key;
		Service* service;
		DependenciesCollection dependencies;
	};

	typedef std::vector< ServiceHolder > ServicesColletion;
	//! @}

private : //! @name Helpers
	//! @{
	friend struct ServiceDependencyComp;

	ServiceHolder& findServiceHolder(const ServiceKey& key);
	const ServiceHolder& findServiceHolder(const ServiceKey& key) const ;
	bool serviceDependsOn(const ServiceKey& service, const ServiceKey& dependency) const ;
	void sortServices();
	bool dependenciesAreReadyForSimulation(const ServiceHolder& svcHolder) const ;
	bool dependenciesAreReadyForMedia(const ServiceHolder& svcHolder) const ;
	//! @}

private : //! @name Constants
	//! @{
	static const ServiceHolder InvalidHolder;
	//!@}

private : // @name Data
	//! @{
	ServicesColletion m_services;
	bool m_servicesAreSorted;
	bool m_updatesMedia;
	//! @}
};

} // namespace infinity

#include "servicemanager.inl"

#endif // !INFINITY_SERVICE_MANAGER_H
